package com.fxm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fxm.constant.TimeConstants;
import com.fxm.dao.ErrorMapper;
import com.fxm.domain.Error;
import com.fxm.domain.Option;
import com.fxm.domain.Question;
import com.fxm.returns.RespCode;
import com.fxm.returns.RespEntity;
import com.fxm.service.ErrorService;
import com.fxm.service.OptionService;
import com.fxm.service.QuestionService;
import com.fxm.utils.TimeUtilCustomize;
import com.fxm.vo.param.ErrorParam;
import com.fxm.vo.param.OpenParam;
import com.fxm.vo.param.RecordParam;
import com.fxm.vo.result.AnswerResult;
import com.fxm.vo.result.ErrorQuestionResult;
import com.fxm.vo.result.ErrorResult;
import com.fxm.vo.result.QuestionResult;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 错题表 服务实现类
 * </p>
 *
 * @author fxm
 * @since 2021-02-25
 */
@Slf4j
@Service
public class ErrorServiceImpl extends ServiceImpl<ErrorMapper, Error> implements ErrorService {

    @Autowired
    private QuestionService questionService;

    @Autowired
    private OptionService optionService;

    @Override
    public RespEntity<List<ErrorResult>> errorList(OpenParam openParam) {

        //获取当前用户所有的错题集
        List<Error> errorList = getErrorList(openParam);

        //错题集 按照日期 分组
        Map<String, List<Error>> errorMap = dataMapping(errorList);

        //错题集数据组装
        List<ErrorResult> errorResultList = errorDataPackage(errorMap);

        //按照时间降序排列
        errorResultList = errorResultList.stream()
                .sorted(Comparator.comparing(ErrorResult::getDate).reversed())
                .collect(Collectors.toList());

        return new RespEntity(RespCode.SUCCESS, errorResultList);
    }

    /**
     * 错题集数据组装
     * @param errorMap
     * @return
     */
    private List<ErrorResult> errorDataPackage(Map<String, List<Error>> errorMap) {
        List<ErrorResult> errorResultList = Lists.newArrayList();
        for (Map.Entry<String, List<Error>> entry : errorMap.entrySet()) {

            //日期处理
            String[] split = entry.getKey().split("-");
            String date = split[1] + "月" + split[2] + "日";

            //数据组装
            ErrorResult errorResult = new ErrorResult();
            errorResult.setDate(date);
            errorResult.setNum(entry.getValue().size());

            errorResultList.add(errorResult);
        }
        return errorResultList;
    }

    private Map<String, List<Error>> dataMapping(List<Error> errorList) {
        Map<String, List<Error>> errorMap = Maps.newHashMap();

        for (Error error : errorList) {

            if (errorMap.containsKey(error.getDate())) {
                errorMap.get(error.getDate()).add(error);
                continue;
            }

            List<Error> list = Lists.newArrayList();
            list.add(error);
            errorMap.put(error.getDate(), list);
        }
        return errorMap;
    }

    /**
     * 获取当前用户所有的错题集
     * @param openParam
     * @return
     */
    private List<Error> getErrorList(OpenParam openParam) {
        QueryWrapper<Error> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Error::getOpenid, openParam.getOpenid())
                             .eq(Error::getDeleted ,0);
        List<Error> errorList = baseMapper.selectList(queryWrapper);
        return errorList;
    }

    @Override
    public RespEntity<List<ErrorQuestionResult>> queryErrorQuestion(ErrorParam errorParam) {
        //日期参数 格式处理
        errorParam = dealDateParam(errorParam);

        //查询该用户当天的错题集
        QueryWrapper<Error> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Error::getOpenid, errorParam.getOpenid())
                             .eq(Error::getDate, errorParam.getDate())
                             .eq(Error::getDeleted, 0)
                             .orderByDesc(Error::getId);
        List<Error> errorList = baseMapper.selectList(queryWrapper);

        //数据组装
        List<ErrorQuestionResult> questionResultList = questionDataPackage(errorList);

        return new RespEntity(RespCode.SUCCESS, questionResultList);
    }

    /**
     * 日期参数格式处理
     * @param errorParam
     * @return
     */
    private ErrorParam dealDateParam(ErrorParam errorParam) {
        String[] split = errorParam.getDate().split("月");
        String date = TimeConstants.YEAR + "-" + split[0] + "-" + split[1].split("日")[0];
        errorParam.setDate(date);
        return errorParam;
    }

    /**
     * 数据组装
     * @param errorList
     * @return
     */
    private List<ErrorQuestionResult> questionDataPackage(List<Error> errorList) {
        List<ErrorQuestionResult> questionResultList = Lists.newArrayList();

        for (Error error : errorList) {
            Question question = questionService.getById(error.getQuestionId());
            ErrorQuestionResult questionResult = new ErrorQuestionResult();
            questionResult.setQuestionId(question.getId());
            questionResult.setQuestion(question.getQuestionTitle());
            questionResult.setType(question.getQuestionType());
            questionResult.setUserAnswer(error.getUserAnswer());

            //查询选项
            QueryWrapper<Option> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(Option::getQuestionId, question.getId())
                    .eq(Option::getDeleted, 0);
            List<Option> optionList = optionService.list(queryWrapper);

            questionResult.setOptionList(optionList);
            questionResultList.add(questionResult);
        }

        return questionResultList;
    }

    @Async
    @Override
    public void errorDataAccess(RecordParam recordParam) {
        log.info("recordParam = {}", recordParam);
        //非null校验
        if (Objects.isNull(recordParam) || Objects.isNull(recordParam.getIsRight())) {
            return;
        }
        //排除正确答题记录
        if (recordParam.getIsRight().equals(0)) {
            return;
        }
        //数据组装
        Error error = dataPackage(recordParam);
        //添加错题记录
        baseMapper.insert(error);
        log.info("异步错题记录接入成功, error={}", error);
    }


    /**
     * 数据组装
     * @param recordParam
     * @return
     */
    private Error dataPackage(RecordParam recordParam) {

        String userAnswer = getUserAnswer(recordParam.getUserAnswer());

        Error error = Error.builder()
                .date(TimeUtilCustomize.parseDateToStr(TimeUtilCustomize.DATE_DAY_FORMAT, new Date()))
                .openid(recordParam.getOpenid())
                .questionId(recordParam.getQuestionId())
                .userAnswer(userAnswer)
                .build();
        return error;
    }

    /**
     * 用户选择
     * @param userAnswer
     * @return
     */
    private String getUserAnswer(Integer userAnswer) {
        String choose = null;

        switch (userAnswer) {
            case 0 : choose = "A"; break;
            case 1 : choose = "B"; break;
            case 2 : choose = "C"; break;
            case 3 : choose = "D"; break;
            default: choose = "放弃答题";
        }

        return choose;
    }
}
